//#pragma code
/******************************************************************************
  Project:    Race and Mission Zeitmessung
  Modul:      com.c
  Descr:      serielle Schnittstelle
  Date:       07.03.04
  Autor:      ge
  Notes:      -
******************************************************************************/

#include "main.h"
#include "com.h"
#include "pc.h"


//interne Moduldefines --------------------------------------------------------
#define COM_TX_BUFFER_SIZE   32
void COM_vOut(void);


//interne Modulvariable -------------------------------------------------------
volatile uc       fComTransmission;                   //FALSE: gerade kein Senden aktiv
volatile uc       aucOutBuffer[COM_TX_BUFFER_SIZE];   //SendeBuffer
volatile uc       ucOutWritePtr;                      //SchreibZeiger fuer OutBuffer
volatile uc       ucOutReadPtr;                       //LeseZeiger fuer OutBuffer


// Allgemeine Fkt -------------------------------------------------------------
void COM_vIniCOM(void)
{
  fComTransmission  = FALSE;
  ucOutWritePtr     = 0;
  ucOutReadPtr      = 0;

}



//Rx Msg ----------------------------------------------------------------------
//uc   COM_ucRxData(uc * pucData);  //nur wenn ohne Interrupt gearbeitet wird


//Tx Msg ----------------------------------------------------------------------
//#############################################################################
void COM_vTxByte(uc ucData)
{
  if(ucOutWritePtr >= ucOutReadPtr)
  {
    if((ucOutWritePtr - ucOutReadPtr) <= (COM_TX_BUFFER_SIZE-2))
    {
      //Platz im Buffer...
      cli();                                 //global interrupt ausschalten 
      aucOutBuffer[ucOutWritePtr] = ucData;
      ucOutWritePtr = (ucOutWritePtr + 1) % COM_TX_BUFFER_SIZE;
      sei();                                 //global Interrupt einschalten
      COM_vOut();

    }
  }
  else
  {
    if((ucOutReadPtr - ucOutWritePtr) > 1)
    {
      //noch Platz
      cli();                                 //global interrupt ausschalten 
      aucOutBuffer[ucOutWritePtr] = ucData;
      ucOutWritePtr = (ucOutWritePtr + 1) % COM_TX_BUFFER_SIZE;
      sei();                                 //global Interrupt einschalten

      COM_vOut();

    }
  }
}//end COM_vTxByte




//#############################################################################
void COM_vOut(void)
{
  if(fComTransmission == FALSE)
  {
    //Es wird gerade nicht auf den TX interrupt gewartet, also senden

    if(ucOutWritePtr != ucOutReadPtr)
    {
      //Es gibt was zum senden
      UDR = aucOutBuffer[ucOutReadPtr];
      ucOutReadPtr = (ucOutReadPtr + 1) % COM_TX_BUFFER_SIZE;
      fComTransmission = TRUE;
    }
    else
    {
      //es gibt nix zum senden
      fComTransmission = FALSE;
    }
  }
  else
  {
    //es wird gerade auf den TX Interrupt gewartet,
    //es darf also nix gesendet werden
  }
}//end COM_vOut()

//-----------------------------------------------------------------------------
void COM_vTxBytes(uc * ucData, uc ucAnzahl){;};



//interne Fkt -----------------------------------------------------------------
//UART Rx Interrupt
SIGNAL (SIG_UART_RECV)
{
  PC_vRxMsg(UDR);
}

//UART Tx Interrupt
//SIGNAL (SIG_UART_TRANS) //Tx fertig
SIGNAL (SIG_UART_DATA)    //Datenspeicher fuer naechstes TxByte frei
{
  fComTransmission = FALSE;
  COM_vOut();
}


